package com.cskaoyan.wordmemorize.service.impl;

import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.converter.RolePermissionConverter;
import com.cskaoyan.wordmemorize.dao.entity.PermissionDO;
import com.cskaoyan.wordmemorize.dao.entity.RoleDO;
import com.cskaoyan.wordmemorize.dao.entity.RolePermissionDO;
import com.cskaoyan.wordmemorize.dao.mapper.PermissionMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RolePermissionMapper;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PermissionCommand;
import com.cskaoyan.wordmemorize.request.RoleCommand;
import com.cskaoyan.wordmemorize.request.RolePermissionCommand;
import com.cskaoyan.wordmemorize.service.RolePermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.management.relation.Role;
import javax.naming.Name;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RolePermissionServiceImpl implements RolePermissionService {

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    RolePermissionConverter rolePermissionConverter;

    @Autowired
    RolePermissionMapper rolePermissionMapper;

    @Autowired
    PermissionMapper permissionMapper;

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_ADD)
    public void savePermissions(PermissionCommand command) {
        PermissionDO permission = rolePermissionConverter.command2PermissionDO(command);
        permissionMapper.insert(permission);
        List<PermissionCommand> children = command.getChildren();
        if (children != null && !children.isEmpty()) {
            for (PermissionCommand childCommand : children) {
                childCommand.setParentPermission(permission.getId().toString());
                savePermissions(childCommand);
            }
        }
    }

    @Override
    public List<PermissionDTO> getPermissions() {
        List<PermissionDTO> topPermissions = permissionMapper.selectByParentId(-1L);
        return topPermissions;
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    public DeletePermissionOperateDTO deletePermission(Long permissionId) {
        PermissionDO permission = permissionMapper.selectById(permissionId);
        if (permission == null) {
            return new DeletePermissionOperateDTO();
        }

        permissionMapper.deleteById(permissionId);

        DeletePermissionOperateDTO result = new DeletePermissionOperateDTO();
        result.setId(permission.getId());
        result.setName(permission.getName());

        result.setPermissionAlias(permission.getPermissionAlias());
        return result;
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_UPDATE)
    public void updatePermission(PermissionCommand command) {
        PermissionDO permissionDO = rolePermissionConverter.command2PermissionDO(command);
        permissionMapper.updateById(permissionDO);
    }

    @Override
    public PageDTO<RoleDTO> getRoleList(PageRequest pageRequest) {

        if (pageRequest.getPageNum() == null) {
            List<RoleDO> roleDOS = roleMapper.selectList(null);
            return rolePermissionConverter.roleList2Page(roleDOS, (long) roleDOS.size());
        }

        Integer pageNum = pageRequest.getPageNum();
        Integer pageSize = pageRequest.getCount();
        String keyword = pageRequest.getKeyword();

        Page<RoleDO> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<RoleDO> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.like(RoleDO::getName, keyword);
        }
        Page<RoleDO> rolePage = roleMapper.selectPage(page, queryWrapper);
        List<RoleDO> records = rolePage.getRecords();
        long total = rolePage.getTotal();
        PageDTO<RoleDTO> roleDTO = rolePermissionConverter.roleList2Page(records, total);
        return roleDTO;
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_ADD)
    public void addRole(RoleCommand command) {
        RoleDO roleDO = rolePermissionConverter.command2RoleDO(command);
        // PageDTO<RoleDTO> roleList = this.getRoleList();
        roleMapper.insert(roleDO);
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_UPDATE)
    public void updateRole(RoleCommand roleCommand) {
        // String id = roleCommand.getId();

        RoleDO roleDO = rolePermissionConverter.command2RoleDO(roleCommand);
        roleMapper.updateById(roleDO);
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_UPDATE)
    public void updateRolePermission(RolePermissionCommand command) {
        Long roleId = Long.valueOf(command.getRoleId());
        rolePermissionMapper.deleteByRoleId(roleId);
        List<Long> permissionIds = command.getPermissions().stream()
                .map(Long::valueOf).distinct()
                .collect(Collectors.toList());

        if (!permissionIds.isEmpty()) {
            List<RolePermissionDO> relationList = permissionIds.stream()
                    .map(permissionId -> {
                        RolePermissionDO relation = new RolePermissionDO();
                        relation.setRoleId(roleId);
                        relation.setPermissionId(permissionId);
                        return relation;
                    })
                    .collect(Collectors.toList());
            rolePermissionMapper.insertOrUpdate(relationList);
        }
    }

    @Override
    public RolePermissionDTO getRolePermissionList(Long roleId) {
        List<PermissionDTO> systemPermissions = this.getPermissions();

        List<String> leafPermissionCodes = rolePermissionMapper.selectLeafPermissionIds(roleId);
        RolePermissionDTO dto = new RolePermissionDTO();
        dto.setSystemPermissions(systemPermissions);
        dto.setAssignedPermissions(leafPermissionCodes);
        return dto;
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    public DeleteRoleOperateDTO deleteRole(Long roleId) {
        if (roleId == null) {
            throw new IllegalArgumentException("角色ID不能为空");
        }

        RoleDO roleDO = roleMapper.selectById(roleId);
        if (roleDO == null) {
            throw new RuntimeException("角色不存在");
        }

        LambdaQueryWrapper<RoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleDO::getId, roleId);
        int deleted = roleMapper.delete(wrapper);

        DeleteRoleOperateDTO dto = new DeleteRoleOperateDTO();
        dto.setId(roleId);
        dto.setName(roleDO.getName());
        return dto;
    }

    @Override
    @OperateLog(dateType = "权限", operateType = OperateLogConstant.OPERATE_BATCH_DELETE)
    public DeleteRolePermissionOperateDTO deleteRolePermission(Long roleId, Long permissionId) {
        DeleteRolePermissionOperateDTO deleteRolePermissionOperateDTO = new DeleteRolePermissionOperateDTO();
        deleteRolePermissionOperateDTO.setRoleId(roleId);
        RoleDO roleDO = roleMapper.selectById(roleId);
        deleteRolePermissionOperateDTO.setRoleName(roleDO.getName());
        deleteRolePermissionOperateDTO.setPermissionId(permissionId);
        PermissionDO permissionDO = permissionMapper.selectById(permissionId);
        deleteRolePermissionOperateDTO.setPermissionAlias(permissionDO.getPermissionAlias());
        int i = rolePermissionMapper.updateIsDeletedByRoleIdAndPermissionId(roleId, permissionId);

        return deleteRolePermissionOperateDTO;
    }
}
